package com.cse587.gae.dao;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
import javax.jdo.Query;

import org.springframework.stereotype.Component;

import com.cse587.gae.dao.CountryDao;
import com.cse587.gae.entities.Country;
import com.cse587.gae.entities.CountryNameToken;
import com.cse587.gae.entities.GDP;
import com.cse587.gae.entities.HDI;
import com.cse587.gae.entities.LandArea;
import com.cse587.gae.entities.Population;
import com.cse587.util.InputException;
import com.cse587.util.PMF;
import com.cse587.util.Util;

@Component
public class CountryDao {
	public List<Country> getAll() {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		String query = "select from " + Country.class.getName()
				+ " order by codeISO3";
		List<Country> countryList = (List<Country>) pm.newQuery(query)
				.execute();
		// pm.close();
		return countryList;
	}

	public void deleteAll() {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Transaction tx = pm.currentTransaction();

		String query = "select from " + Country.class.getName()
				+ " order by codeISO3";
		List<Country> countryList = (List<Country>) pm.newQuery(query)
				.execute();

		for (Country country : countryList) {
			tx.begin();
			pm.deletePersistent(country);
			tx.commit();
		}
	}

	public boolean deleteCountryByIso3Code(String iso3Code) {
		boolean status = false;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		tx.begin();
		Set<String> iso3 = new HashSet<String>();
		List<Country> countryList = getCountryListByIso3Code(iso3);

		if (countryList.size() > 0) {
			pm.deletePersistent(countryList);
			status = true;
		} else {
			status = false;
		}

		tx.commit();
		return status;
	}

	public List<Country> getCountryListByIso3Code(Set<String> iso3Code) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(Country.class);
		query.setFilter("codeISO3 == :codeISO3Param");
		// query.declareParameters("String codeISO3Param");

		List<Country> results = (List<Country>) query.execute(iso3Code);
		try {
			if (!results.isEmpty()) {
				return results;
			} else {
				return new ArrayList<Country>();
			}
		} finally {
			query.closeAll();
		}
	}

	public Country getCountryByIso3Code(String iso3Code) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(Country.class);
		query.setFilter("codeISO3 == :codeISO3Param");
		// query.declareParameters("String codeISO3Param");

		List<Country> results = (List<Country>) query.execute(iso3Code);
		try {
			if (!results.isEmpty()) {
				return results.get(0);
			} else {
				return null;
			}
		} finally {
			query.closeAll();
		}
	}

	public List<Country> getCountryByName(String name) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(Country.class,
				":p.contains(alternativeName) || fullName == fullNameParam");
		// query.declareParameters("String fullNameParam");

		List<Country> results = (List<Country>) query.execute(Arrays.asList(
				name, name));
		try {
			if (!results.isEmpty()) {
				return results;
			} else {
				return new ArrayList<Country>();
			}
		} finally {
			query.closeAll();
		}
	}

	public Country getCountryByCoordinates(Double lat, Double longtitude) throws InputException {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query maxLongQuery = pm.newQuery(Country.class);
		// maxLongQuery.setFilter("maxLong.contains(:longtitude) && minLat.contains(:lat)");
		maxLongQuery.setFilter("maxLong > " + longtitude);
		maxLongQuery
				.setOrdering("maxLong desc minLong desc latMax desc latMin desc");
		List<Country> result1 = (List<Country>) maxLongQuery.execute();
		maxLongQuery.closeAll();
		List<Country> result = new ArrayList<Country>();
		for (Country country : result1) {
			if (country.getMinLong() < longtitude && country.getMaxLat() > lat
					&& country.getMinLat() < lat)
				result.add(country);
		}
		// result1.retainAll(result2);
		if( result.size() > 0 ){
			return result.get(0);
		}else{
			throw new InputException(Util.FAIL_TO_LOCATE_BY_LAT_LONG);
		}
	}

	public List<Country> getCountryByBorder(String borders) {
		List<Country> result = new ArrayList<Country>();
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(Country.class);
		query.setFilter("borders.contains(:borders)");
		result = (List<Country>) query.execute(borders);

		return result;
	}

	public List<CountryNameToken> getTokens(String name){
		List<CountryNameToken> result = new ArrayList<CountryNameToken>();
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(CountryNameToken.class);
		String filterString = "";
		String[] rowArray = name.split(" ");
		for (int i = 0; i<rowArray.length;i++) {
			filterString += "token == '"+rowArray[i]+"'";
			if( i < rowArray.length -1 )
				filterString += " || ";
		}
		query.setFilter(filterString);
		
		result = (List<CountryNameToken>) query.execute();
		return result;
	}

	public List<CountryNameToken> getAllToken() {
		List<CountryNameToken> result = new ArrayList<CountryNameToken>();
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(CountryNameToken.class);
		result = (List<CountryNameToken>) query.execute();
		return result;
	}
	// public List<Country> getCountryListByFeature(String featureName, String
	// order){
	// PersistenceManager pm = PMF.get().getPersistenceManager();
	// Query query = pm.newQuery(Country.class);
	// query.setFilter("");
	// //List<Country> countryList = (List<Country>)
	// pm.newQuery(query).execute();
	// //pm.close();
	// return countryList;
	// }
}
